package com.gzhryc.weixin.xcx;

import com.gzhryc.weixin.api.DefaultApiResponse;
import com.gzhryc.weixin.gzh.WxAuthorityApi;
import com.gzhryc.weixin.gzh.models.AccessToken;
import com.gzhryc.weixin.gzh.msg.AccessTokenResponse;
import org.apache.log4j.Logger;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class WeixinXcxApiService {
	
	static Logger log = Logger.getLogger(WeixinXcxApiService.class);
	
	private Timer timer;
	
	private final AccessToken accessToken;
	private WxAuthorityApi authorityApi;
	
	public WeixinXcxApiService(String appid,String secret){
		this.accessToken = new AccessToken(appid,secret);
		this.timer = new Timer();
		this.authorityApi = new WxAuthorityApi(accessToken);
	}

	public void run(RunningEvent runningEvent){
		accessToken.isRunning(true);
		//第一次启动获取token
		AccessTokenResponse accessTokenResponse = authorityApi.getAccessTokenResponse();
		if(accessTokenResponse != null){
			accessToken.setAccess_token(accessTokenResponse.getAccess_token());
			accessToken.setExpires_in(accessTokenResponse.getExpires_in());
			GetTokenTimerTask.start(this);
			if(runningEvent != null){
 				runningEvent.started(accessToken);
 			}
		}
		new Thread(() -> {
			while(accessToken.isRunning()){
				try {
					DefaultApiResponse entity = accessToken.queueTake();
					log.info("处理微信API错误结果，错误码："+entity.getErrcode());
					if(40001 == entity.getErrcode() || 40014 == entity.getErrcode()
							|| 42001 == entity.getErrcode()){
						log.info("处理access_token错误，目前出现该错误的原因是有其它程序争取凭证");
						//检查错误时间与最新的入口凭证获取时间，避免重复获取
						log.info("时间对比："+accessToken.getLastSetDate() + ":"+entity.getCreateDate());
						if(entity.getCreateDate().after(accessToken.getLastSetDate())){
							AccessTokenResponse accessTokenResponse1 = authorityApi.getAccessTokenResponse();

							if(accessTokenResponse1 == null){
								log.error("获取微信普通AccessToken失败！！！");
							}else{
								accessToken.setAccess_token(accessTokenResponse1.getAccess_token());
								accessToken.setExpires_in(accessTokenResponse1.getExpires_in());
							}
						}
					}
				} catch (Exception e) {
					log.error("微信API响应处理失败～～");
					e.printStackTrace();
				}
			}
		}).start();
	}
	
	public void stop(){
		this.accessToken.isRunning(false);
	}
	
	public AccessToken getAccessToken(){
		return this.accessToken;
	}
	
	public XcxAuthorityApi getXcxAuthorityApi(){
		return new XcxAuthorityApi(this.accessToken.getAppid(),this.accessToken.getSecret());
	}
	
	public XcxQrcodeApi getXccQrcodeApi(){
		return new XcxQrcodeApi(this.accessToken);
	}
	
	public WxAuthorityApi getAuthorityApi(){
		return this.authorityApi;
	}
	
	public static class GetTokenTimerTask extends TimerTask {
		
		final WeixinXcxApiService apiSer;
		
		public GetTokenTimerTask(WeixinXcxApiService apiSer){
			this.apiSer = apiSer;
		}

		@Override
		public void run() {
			try{
				if(apiSer != null && apiSer.getAccessToken() != null && apiSer.getAccessToken().getExpires_in() != null){
					//超过三分之一的时间就重新刷新
					Long flag = apiSer.getAccessToken().getExpires_in() - (apiSer.getAccessToken().getExpires_in()/3);
					Long temp = (System.currentTimeMillis() - apiSer.getAccessToken().getLastSetDate().getTime())/1000;
					if(temp > flag){
						AccessTokenResponse accessTokenResponse = apiSer.getAuthorityApi().getAccessTokenResponse();
						if(accessTokenResponse == null){
							log.error("获取微信普通AccessToken失败！！！");
						}else{
							apiSer.accessToken.setAccess_token(accessTokenResponse.getAccess_token());
							apiSer.accessToken.setExpires_in(accessTokenResponse.getExpires_in());
							apiSer.accessToken.setLastSetDate(new Date());
						}
					}
				}else{
					//如果为空则直接刷新
					AccessTokenResponse accessTokenResponse = apiSer.getAuthorityApi().getAccessTokenResponse();
					if(accessTokenResponse == null){
						log.error("获取微信普通AccessToken失败！！！");
					}else{
						apiSer.accessToken.setAccess_token(accessTokenResponse.getAccess_token());
						apiSer.accessToken.setExpires_in(accessTokenResponse.getExpires_in());
					}
				}
			}catch(Exception e){
				e.printStackTrace();
			}finally{
				GetTokenTimerTask.start(apiSer);
			}
		}
		
		public static void start(WeixinXcxApiService apiSer){
			//定时刷新
			if(apiSer.accessToken.isRunning()){
				Long delay = 7000000L;
				if(apiSer.getAccessToken() != null && apiSer.getAccessToken().getExpires_in() != null){
					delay = apiSer.getAccessToken().getExpires_in()*1000 - 300000;
				}
				apiSer.timer.schedule(new GetTokenTimerTask(apiSer),delay);
			}
		}
	}
	
	public static interface RunningEvent {
		
		public void started(AccessToken accessToken);
	}
}
